package cn.tristenstudy.blog.service.impl;

import cn.tristenstudy.blog.mapper.CommentMapper;
import cn.tristenstudy.blog.pojo.Comment;
import cn.tristenstudy.blog.pojo.User;
import cn.tristenstudy.blog.pojo.dto.CommentDTO;
import cn.tristenstudy.blog.service.CommentService;
import cn.tristenstudy.blog.util.EmailUtil;
import cn.tristenstudy.blog.util.SensitiveWordUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author xichen1.li
 * @date 2021-01-11 15:49
 */
@Service
@Transactional
public class CommentServiceImpl implements CommentService {

    @Autowired
    private SensitiveWordUtil sensitiveWordUtil;
    @Autowired
    private EmailUtil emailUtil;
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${exchange.name}")
    private String exchangeName;
    @Value("${queue.name}")
    private String queueName;
    @Value("${comment.avatar}")
    private String avatar;
    @Value("${file.url}")
    private String fileUrl;

    private static final Lock MY_LOCK = new ReentrantLock();

    /**
     * 存放迭代找出所有子代集合
     */
    private List<CommentDTO> temReplys = new ArrayList<>();

    @Override
    public List<CommentDTO> listComment(Long blogId) {
        List<CommentDTO> commentList = commentMapper.findByBlogId(blogId);
        combineChildren(commentList);
        return commentList;
    }

    @Override
    public void insertComment(CommentDTO commentDTO) {
        MY_LOCK.lock();
        try {
            Comment comment = new Comment();
            String nickName = commentDTO.getNickName();
            String content = commentDTO.getContent();
            nickName = sensitiveWordUtil.replaceWords(nickName);
            content = sensitiveWordUtil.replaceWords(content);
            commentDTO.setNickName(nickName);
            commentDTO.setContent(content);
            Long parentId = commentDTO.getParentId();
            comment.setBlogId(commentDTO.getBlogId());
            comment.setContent(commentDTO.getContent());
            //获取当前用户
            Subject subject = SecurityUtils.getSubject();
            User currentUser = (User) subject.getPrincipal();
            if (currentUser != null) {
                comment.setAdminComment(true);
                comment.setEmail(currentUser.getEmail());
                comment.setAvatar(currentUser.getAvatar());
                comment.setNickname(currentUser.getNickName());
            } else {
                comment.setAdminComment(false);
                comment.setEmail(commentDTO.getEmail());
                comment.setAvatar(avatar);
                comment.setNickname(commentDTO.getNickName());
                sendEmail(comment);
                comment.setSend(true);
            }
            comment.setParentId(parentId);
            comment.setCreateTime(new Date());
            comment.setDelFlag(0);
            commentMapper.insert(comment);
        } finally {
            MY_LOCK.unlock();
        }
    }

    /**
     * 合并评论的各层子代到第一级子代集合中
     *
     * @param comments 评论集合
     */
    private void combineChildren(List<CommentDTO> comments) {
        for (CommentDTO comment : comments) {
            List<CommentDTO> replayComments = comment.getReplayComments();
            for (CommentDTO replayComment : replayComments) {
                //循环迭代，找出子代，存放在存temReplys中
                recursively(replayComment);
            }
            //修改顶级节点的replay集合为迭代处理后的集合
            comment.setReplayComments(temReplys);
            //清除临时存放区
            temReplys = new ArrayList<>();
        }
    }

    /**
     * 递归迭代，剥洋葱
     *
     * @param replayComment 评论详情
     */
    private void recursively(CommentDTO replayComment) {
        //顶节点添加到临时存放集合
        temReplys.add(replayComment);
        if (replayComment.getReplayComments().size() > 0) {
            List<CommentDTO> replayComments = replayComment.getReplayComments();
            for (CommentDTO comment : replayComments) {
                if (comment.getReplayComments().size() > 0) {
                    recursively(comment);
                } else {
                    temReplys.add(comment);
                }
            }
        }
    }

    /**
     * 邮件任务，每天中午12点和晚上10点发送邮件
     * 后期通过rabbitMQ发送邮件
     */
    @Scheduled(cron = "0 0 12,22 * * ?")
    @Override
    @Deprecated
    public void sendEmail() {
        QueryWrapper<Comment> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "blog_id", "nickname", "email", "send");
        queryWrapper.eq("blog_id", 1L);
        queryWrapper.eq("admin_comment", false);
        queryWrapper.eq("del_flag", 0);
        queryWrapper.eq("send", false);
        List<Comment> comments = commentMapper.selectList(queryWrapper);
        for (Comment comment : comments) {
            Long blogId = comment.getBlogId();
            String nickName = comment.getNickname();
            if (blogId == 1) {
                String encoding = "utf-8";
                String subject = "STM32仿真课件";
                String text = "<h3>Dear <span style=\"color: #00aaaa\">" + nickName + "</span>:</h3><p style=\"text-indent: 30px;font-size: 15px\">感谢你的支持，请查收STM32课件~</p>";
                String path = fileUrl;
                String fileName = "STM32仿真课设.zip";
                String sendTo = comment.getEmail();
                String sendFrom = "2519294308@qq.com";
                try {
                    emailUtil.sendMail(true, encoding, subject, text, path, fileName, sendTo, sendFrom);
                    comment.setSend(true);
                    commentMapper.updateById(comment);
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 通过rabbitmq发送邮件
     *
     * @param comment 评论信息
     */
    public void sendEmail(Comment comment) {
        String email = comment.getEmail();
        String nickName = comment.getNickname();
        rabbitTemplate.convertAndSend(exchangeName, "email.send", email + ":" + nickName);
    }

}
